package com.douqu.game.main.server;


import com.alibaba.fastjson.JSONObject;
import com.bean.core.buffer.ByteBuffer;
import com.douqu.game.core.controller.PlayerController;
import com.douqu.game.core.e.E_ApplyCampActivityType;
import com.douqu.game.core.e.E_NoticeType;
import com.douqu.game.core.e.E_ServerType;
import com.douqu.game.core.entity.Player;
import com.douqu.game.core.entity.activity.MatchBaseInfo;
import com.douqu.game.core.entity.battle.PlayerBattleData;
import com.douqu.game.core.factory.CodeFactory;
import com.douqu.game.core.factory.ConfigFactory;
import com.douqu.game.core.netty.NettyConnection;
import com.douqu.game.core.util.LogUtils;
import com.douqu.game.main.GameServer;
import com.douqu.game.main.server.entity.ServerInfo;
import com.douqu.game.main.server.entity.ServerInfoActivity;
import com.douqu.game.main.server.entity.ServerInfoBattle;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * Author : Bean
 * 2017-06-19 16:59
 */
public class ServerManager {

    private List<ServerInfoBattle> battleServerList = new CopyOnWriteArrayList<>();

    private ServerInfo activityServer;

    private static ServerManager instance = null;

    private ServerManager(){}

    public static ServerManager getInstance()
    {
        if(instance == null)
            instance = new ServerManager();

        return instance;
    }

    public void update()
    {
        for(ServerInfo serverInfo : battleServerList)
        {
            serverInfo.update();
        }

        if(activityServer != null)
            activityServer.update();
    }



    public int getBattleServerPort()
    {
        for(int port : ConfigFactory.SERVER_PORT_BATTLE)
        {
            if(getBattleServerInfo(port) == null)
                return port;
        }
        return 0;
    }

    public List<ServerInfoBattle> getBattleServerList()
    {
        return battleServerList;
    }


    public void addServerInfo(E_ServerType serverType, NettyConnection connection, int port)
    {
        connection.setServerType(serverType);

        LogUtils.warn("添加新的分支服务器:" + serverType + " ip:" + connection + " port:" + port);

        if(E_ServerType.BATTLE == serverType)
        {
            if(getBattleServerInfo(port) != null)
                return;

            ServerInfoBattle serverInfo = new ServerInfoBattle(serverType, connection, port);
            connection.setObject(serverInfo);

            battleServerList.add(serverInfo);

            LogUtils.warn("添加新的战斗服务器成功:" + serverType + " host:" + serverInfo.getHost() + " port:" + port);

            sendToBattleServerLogConfig();
        }
        else if(E_ServerType.ACTIVITY == serverType)
        {
            if(activityServer != null)
                return;

            activityServer = new ServerInfoActivity(serverType, connection, port);
            connection.setObject(activityServer);
            activityServer.setHttpPort(ActivityCampManager.getInstance().getHttpPort());

            LogUtils.warn("添加新的活动服务器成功:" + serverType + " host:" + activityServer.getHost());

            sendToActivityServerLogConfig();
        }
    }

    public void removeServerInfo(NettyConnection connection)
    {
        if(connection.getObject() instanceof ServerInfoBattle)
        {
            ServerInfoBattle serverInfoBattle = (ServerInfoBattle) connection.getObject();
            for(ServerInfoBattle serverInfo : battleServerList)
            {
                if(serverInfo.getPort() == serverInfoBattle.getPort())
                {
                    LogUtils.warn("战斗服务器断开连接:" + serverInfo);
                    serverInfo.destroy();
                    battleServerList.remove(serverInfo);
                    break;
                }
            }

            LogUtils.warn("删除后的战斗服务器列表 -> " + battleServerList);
        }
        else if(connection.getObject() instanceof ServerInfoActivity)
        {
            if(activityServer != null)
            {
                activityServer.destroy();
                activityServer = null;
            }
        }
    }


    public ServerInfoBattle getBattleServerInfo(int port)
    {
        for(ServerInfoBattle serverInfo : battleServerList)
        {
            if(serverInfo.getPort() == port)
                return serverInfo;
        }
        return null;
    }


    public ServerInfoBattle getFreeBattleServer()
    {
        if(battleServerList.isEmpty())
            return null;

        if(battleServerList.size() == 1)
            return battleServerList.get(0);

        ServerInfoBattle result = Collections.min(battleServerList, new Comparator<ServerInfoBattle>() {
            @Override
            public int compare(ServerInfoBattle o1, ServerInfoBattle o2) {

                return new Integer(o1.getBattleCount()).compareTo(o2.getBattleCount());
            }
        });

//        LogUtils.info("获取空闲战斗服务器:" + result);

        return result;
    }


    /**
     * 告诉战斗服务器配置文件重新加载了
     */
   public void sendLoadData()
   {
       for(ServerInfoBattle serverInfo : battleServerList)
       {
            serverInfo.sendMsg(CodeFactory.LOAD_DATA, null);
       }
   }

    /**
     * 此方法参数是后加的，现在线上的的代码不能热更
     * @param path
     */
    public void sendUpdateClass(String path)
    {
        ByteBuffer buffer = new ByteBuffer();
        buffer.writeUTF(path);
        for(ServerInfoBattle serverInfo : battleServerList)
        {
            serverInfo.sendMsg(CodeFactory.UPDATE_CLASS, buffer.getBytes());
        }
    }

    /**
     * 通知阵营战服务器更新配置
     */
    public void sendToActivityUpdateConfig(String path, String version)
    {
        if(activityServer == null)
            return;

        ByteBuffer buffer = new ByteBuffer();
        buffer.writeUTF(path);
        buffer.writeUTF(version);
        activityServer.sendMsg(CodeFactory.LOAD_DATA, buffer.getBytes());
    }

    public void sendUpdateLogLevel()
    {
        sendToBattleServerLogConfig();

        sendToActivityServerLogConfig();
    }

    public void sendToBattleServerLogConfig()
    {
        ByteBuffer buffer = new ByteBuffer();
        buffer.writeUTF(ConfigFactory.gmSetting.getBattleLog().name());
        buffer.writeBoolean(ConfigFactory.gmSetting.isBattleTimeoutToAI());

        for(ServerInfo serverInfo : battleServerList)
        {
            serverInfo.sendMsg(CodeFactory.UPDATE_LOG_CONFIG, buffer.getBytes());
        }
    }

    public void sendToActivityServerLogConfig()
    {
        if(activityServer != null)
        {
            ByteBuffer buffer = new ByteBuffer();
            buffer.writeUTF(ConfigFactory.gmSetting.getActivityLog().name());
            buffer.writeUTF(ConfigFactory.gmSetting.getActivityBattleLog().name());
            buffer.writeBoolean(ConfigFactory.gmSetting.isBattleTimeoutToAI());

            activityServer.sendMsg(CodeFactory.UPDATE_LOG_CONFIG, buffer.getBytes());
        }
    }

    public void sendNotice(String content,E_NoticeType... noticeType)
    {
        ByteBuffer buffer = new ByteBuffer();
        if (noticeType != null && noticeType.length > 0){
            buffer.writeByte(noticeType[0].getCode());
        }else{
            buffer.writeByte(E_NoticeType.NOTICE_TYPE_OTHER.getCode());
        }
        buffer.writeUTF(content);
        for(ServerInfo serverInfo : battleServerList)
        {
            serverInfo.sendMsg(CodeFactory.SEND_NOTICE, buffer.getBytes());
        }
    }


    public void sendOffline(PlayerController playerController)
    {
        PlayerBattleData battleData = playerController.getBattleData();
        if(battleData != null)
        {
            ServerInfo serverInfo = getBattleServerInfo(battleData.getBattleServerPort());
            if(serverInfo != null)
            {
                ByteBuffer buffer = new ByteBuffer();
                buffer.writeUTF(battleData.getBattleId());
                buffer.writeUTF(playerController.getObjectIndex());
                serverInfo.sendMsg(CodeFactory.PLAYER_OFFLINE, buffer.getBytes());

                playerController.clearBattle();
            }
        }
    }

    public void sendSystem(PlayerController playerController, String content)
    {
        PlayerBattleData battleData = playerController.getBattleData();
        if(battleData != null)
        {
            ServerInfo serverInfo = getBattleServerInfo(battleData.getBattleServerPort());
            if(serverInfo != null)
            {
                ByteBuffer buffer = new ByteBuffer();
                buffer.writeUTF(battleData.getBattleId());
                buffer.writeUTF(playerController.getObjectIndex());
                buffer.writeUTF(content);
                serverInfo.sendMsg(CodeFactory.PLAYER_SYSTEM, buffer.getBytes());

                playerController.clearBattle();
            }
        }
    }

    /**
     * 通知活动服务器报名成功
     * @param player
     */
    public void sendApplyActivity(Player player, E_ApplyCampActivityType type)
    {
        if(activityServer == null)
            return;

        ByteBuffer buffer = new ByteBuffer();
        buffer.writeUTF(JSONObject.toJSONString(new MatchBaseInfo(player, GameServer.getInstance().getServerId())));
        buffer.writeUTF(type.name());
        activityServer.sendMsg(CodeFactory.ACTIVITY_CAMP_APPLY_SUCCESS, buffer.getBytes());
    }


    public ServerInfo getActivityServer() {
        return activityServer;
    }
}
